package com.qf.homework.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.SyncReadListener;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qf.homework.mapper.RecordMapper;
import com.qf.homework.mapper.StusMapper;
import com.qf.homework.pojos.Record;
import com.qf.homework.pojos.Stus;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.FileUploadException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/hw")
@Slf4j
public class HomeworkController {

    @Value("${hw.base-dir}")
    private String baseDir;

    @Value("${hw.stu-names-file}")
    private String stuNamesFilePath;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    @Autowired
    private StusMapper stusMapper;

    @Autowired
    private RecordMapper recordMapper;

    @PostMapping("/upload")
    public String uploadHw(MultipartFile file) throws IOException {

        if (file == null){
            throw new RuntimeException("请提交作业文件");
        }

        // 作业文件不允许超过10M
        if (file.getInputStream().available() > 10485760){
            throw new MaxUploadSizeExceededException(10485760);
        }

        String dateStr = sdf.format(new Date());
        String fileDir = baseDir + dateStr;

        File dir = new File(fileDir);
        if (!dir.exists()){
            dir.mkdirs();
        }

        log.info("创建作业提交目录成功,作业目录:{}",dir.getAbsolutePath());

        String filename = file.getOriginalFilename();
        if (filename == null){
            throw new RuntimeException("请提交作业文件");
        }

        File destFile = new File(fileDir,filename);

        //避免重复提交同名文件的异常
        try {
            file.transferTo(destFile);
        }catch (IOException e){
            e.printStackTrace();
        }

        //入库
        String name = filename.substring(0,filename.lastIndexOf("."));
        Stus stus = new Stus();
        stus.setName(name);
        stus.setAddr(destFile.getAbsolutePath());
        stus.setStatus(1);
        //计算文件md5值 （用于比对相同内容的作业，防止抄袭）
        String md5 = DigestUtils.md5DigestAsHex(new FileInputStream(destFile));
        stus.setCode(md5);

        LambdaQueryWrapper<Stus> qw = new LambdaQueryWrapper<>();
        qw.eq(Stus::getName,name);
        stusMapper.update(stus,qw);

        return "success";
    }

    @GetMapping("/start")
    public String names() throws Exception {
        String dateStr = sdf.format(new Date());

        //防止同一天多次生成收集名单
        synchronized (this) {
            Record record = recordMapper.selectOne(Wrappers.lambdaQuery(Record.class).eq(Record::getDate, dateStr));
            if (record != null) {
                return "正在收集作业";
            }
        }

        List<String> names = new ArrayList<>();
        File file = new File(stuNamesFilePath);
        EasyExcel.read(file,Stus.class,new SyncReadListener(){
            @Override
            public void invoke(Object object, AnalysisContext context) {
                String name = ((Stus)object).getName();
                names.add(name);
            }
        }).doReadAll();

        log.info("班级总人数:{},学员名单:{}",names.size(),names);

        //插入数据库
        if (names != null){
            for (String name : names) {
                Stus stus = new Stus();
                stus.setName(name);
                stus.setDate(new Date());
                stus.setStatus(0);
                stusMapper.insert(stus);
            }
        }

        Record record = new Record();
        record.setDate(new Date());
        recordMapper.insert(record);

        log.info("需要提交作业名单入库完成~~");

        return "开始成功";
    }

    @GetMapping("/report")
    public Map report(){
        String dateStr = sdf.format(new Date());

        Map map = new HashMap();

        LambdaQueryWrapper<Stus> qw = new LambdaQueryWrapper<>();
        qw.eq(Stus::getDate, dateStr);
        qw.eq(Stus::getStatus,1);
        List<Stus> upStus = stusMapper.selectList(qw);
        if (upStus!=null){
            List<String> upStusName = upStus.stream().map(stus -> stus.getName()).collect(Collectors.toList());
            map.put("upStus",upStusName);
        }

        log.info("已提交学员:{}",upStus);

        qw = new LambdaQueryWrapper<>();
        qw.eq(Stus::getDate,dateStr);
        qw.eq(Stus::getStatus,0);
        List<Stus> noUpStus = stusMapper.selectList(qw);
        if (noUpStus != null){
            List<String> noUpNames = noUpStus.stream().map(stus -> stus.getName()).collect(Collectors.toList());
            map.put("noUpStus",noUpNames);
        }
        log.info("未已提交学员:{}",noUpStus);

        QueryWrapper<Stus> cqw = new QueryWrapper<>();
        cqw.select("*");
        cqw.eq("date",dateStr);
        cqw.eq("status",1);
        Long upNums = stusMapper.selectCount(cqw);
        map.put("upNums",upNums);

        cqw = new QueryWrapper<>();
        cqw.select("distinct(code)");
        cqw.eq("date",dateStr);
        cqw.eq("status",1);
        Long noDistinctNums = stusMapper.selectCount(cqw);
        map.put("noDistinctNums",noDistinctNums);

        return map;
    }
}
